﻿#region << 版 本 注 释 >>

/*----------------------------------------------------------------
 * 创建者：zhaijc
 * 创建时间：2023/4/14 14:21:54
 * 版本：V1.0.0
 * 描述：
 *
 * ----------------------------------------------------------------
 * 修改人：
 * 时间：
 * 修改说明：
 *
 * 版本：V1.0.1
 *----------------------------------------------------------------*/

#endregion << 版 本 注 释 >>

using DotNetty.Buffers;
using DotNetty.Transport.Channels;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Channels;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace MedianSocketService.netty
{
    public class ChannelManager
    {
        public Action<SocketClientInfo, byte[]> OnSendCompletedDelegate;

        #region 单例模式

        private static readonly object _lock = new object();
        private static ChannelManager _instance;

        private ChannelManager()
        { }

        public static ChannelManager GetInstance()
        {
            if (_instance == null)
            {
                lock (_lock)
                {
                    if (_instance == null)
                    {
                        _instance = new ChannelManager();
                    }
                }
            }
            return _instance;
        }

        #endregion

        private readonly ConcurrentDictionary<SocketClientInfo, IChannel> channels = new ConcurrentDictionary<SocketClientInfo, IChannel>();

        public void AddChannel(SocketClientInfo socketClient, IChannel channel)
        {
            channels.AddOrUpdate(socketClient, channel, (s, c) => channel);
        }

        public void RemoveChannel(SocketClientInfo socketClient)
        {
            channels.TryRemove(socketClient, out _);
        }

        public bool TryGetChannel(SocketClientInfo socketClient, out IChannel channel)
        {
            return channels.TryGetValue(socketClient, out channel);
        }

        public void SendDataToClient(SocketClientInfo socketClient, byte[] data)
        {
            if (!channels.TryGetValue(socketClient, out var channel))
            {
                return;
            }
            var message = Unpooled.WrappedBuffer(data);
            channel.WriteAndFlushAsync(message);
            OnSendCompleted(socketClient, data);
        }

        public void SendDataToAllClient(byte[] data)
        {
            foreach (var key in channels.Keys)
            {
                //Task.Run(() => {
                var message = Unpooled.WrappedBuffer(data); 
                channels[key].WriteAndFlushAsync(message);
                OnSendCompleted(key, data);
                //});
            }
        }

        public void OnSendCompleted(SocketClientInfo socketClient, byte[] data)
        {
            if (OnSendCompletedDelegate != null)
            {
                OnSendCompletedDelegate(socketClient, data);
            }
        }

        public void CloseAll()
        {
            foreach (var key in channels.Keys)
            {
                if (channels[key] != null && channels[key].Active)
                {
                    channels[key].CloseAsync();
                }
            }
            channels.Clear();
        }
    }
}